﻿/* HEADER
 * ------
 * © 2009 by Salomon Zwecker 
 * modified by:
 * - 
 */
using System;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Sampler
{
    /// <summary>
    /// A Sample is used to show how to use a component / library
    /// </summary>
    public abstract class Sample
    {
        /// <summary>
        /// The Sample which is currently active.
        /// </summary>
        public static Sample ActiveSample
        {
            get { return SampleManager.Instance._ActiveSample; }
            set { SampleManager.Instance.SetActiveSample(value); }
        }

        /// <summary>
        /// The description text of the sample
        /// </summary>
        public string Descripton { get; set; }

        /// <summary>
        /// The Game class. Use it to get access to the GraphicsDevice, ContentManager, ...
        /// </summary>
        protected Game Game;

        bool _IsInitialized = false;
        /// <summary>
        /// Gets a bool which specifies wether the sample has been initialized.
        /// </summary>
        public bool IsInitialized { get { return _IsInitialized; } }

        internal Point _Resolution = new Point(800, 600);


        /// <summary>
        /// Creates a new Sample and commits itself to the SampleManager
        /// </summary>
        /// <param name="description">the description which will be displayed while the sample is active</param>
        protected Sample(string description)
        {
            if (SampleManager.Instance == null)
                throw new Exception("Create a SampleManager before creating a sample.");
            
            Descripton = description;

            Game = SampleManager.Instance.Game;
        }

        internal void Activate()
        {
            SampleManager.Instance.SetResolution(_Resolution.X, _Resolution.Y);

            if (!_IsInitialized)
                Initialize();

            _IsInitialized = true;

            SampleManager.Instance._ActiveSample = this;
        }

        internal void CallDeActivate()
        {
            DeActivate();
        }

        
        /// <summary>
        /// Use this method to create all your content.
        /// </summary>
        protected abstract void Initialize();

        /// <summary>
        /// you may use this method to do something when the user switches from this sample to another.
        /// if you delete your content here, make sure to call ReInitializeOnNextActivation().
        /// </summary>
        protected virtual void DeActivate()
        {
            GC.Collect();
        }
        /// <summary>
        /// Call this method inside of DeActivate() if you delete your content there.
        /// It will call Initialize() on the next activation of this sample.
        /// </summary>
        protected void ReInitializeOnNextActivation()
        {
            _IsInitialized = false;
        }


        /// <summary>
        /// Is called every Update of the SampleManager if this Sample is active.
        /// </summary>
        /// <param name="seconds">the seconds since the last Update. (To cast the every time from GameTime-Object is annoying...)</param>
        /// <param name="currentButtons">the GamepadState of this update</param>
        /// <param name="previousButtons">the GamepadState of the previous update</param>
        /// <param name="currentKeys">the KeyboardState of the current update</param>
        /// <param name="previousKeys">the KeyboardState of the previous update</param>
        /// <param name="currentMouse">the MouseState of the current update</param>
        /// <param name="previousMouse">the MouseState of the previous update</param>
        public abstract void Update(float seconds,
                                GamePadState currentButtons, GamePadState previousButtons,
                                KeyboardState currentKeys, KeyboardState previousKeys,
                                MouseState currentMouse, MouseState previousMouse);

        /// <summary>
        /// Is called every Draw call of the SampleManager if this Sample is active.
        /// </summary>
        /// <param name="batch">A spriteBatch object with which you can draw 2D-Stuff.</param>
        public abstract void Draw(SpriteBatch batch);

        /// <summary>
        /// returns a string: "Sample {Description}"
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return "Sample {" + Descripton + "}";
        }

        /// <summary>
        /// Sets the Resolution of this sample.
        /// </summary>
        /// <param name="width">the width in pixels of the resolution</param>
        /// <param name="height">the height in pixels of the resolution</param>
        protected void SetResolution(int width, int height)
        {
            if (width == _Resolution.X && height == _Resolution.Y)
                return;

            _Resolution.X = width;
            _Resolution.Y = height;

            if(ActiveSample == this)
                SampleManager.Instance.SetResolution(width, height);

        }
    }
}
